﻿// ===============================================================================
// Project Name        :    Gfw.BLL.Basic.Stock.Facilities
// Project Description :    
// ===============================================================================
// Class Name          :    BargainRecordFacility
// Namespace:          :    Gfw.BLL.Basic.Stock.Facilities
// Class Version       :    v1.0.0.0
// Class Description   :    
// CLR Version:        :    4.0.30319.17626
//Author               :    lif
// Machine             :    ADICO-PC
// Create Time         :    2012/7/14 16:58:59
// Update Time         :    2012/7/14 16:58:59
// ===============================================================================
// Copyright © lif 2012 . All rights reserved.
// ===============================================================================

using System;
using Gfw.Infrastructure.ExceptionImpl;
using Gfw.Infrastructure.Facilities;
using Gfw.Infrastructure.Stock.Enums;
using Gfw.Models.Stock;
using Gfw.Repositories.Admin;
using Gfw.Repositories.Stock;
using Gfw.Repository;

namespace Gfw.Infrastructure.Stock.Facilities
{
    /// <summary>
    /// 股票交易记录功能，这里仅仅完成交易记录一张表
    /// </summary>
    public class BargainFacility : IFacility
    {
        public  const decimal EnforceSell = 0.0658M;

        private string _agencyId;
        private decimal _count;
        private decimal _price;


        public BargainFacility(string agencyId, decimal price,
                                     decimal count)
        {
            _price = price;
            _count = count;
            _agencyId = agencyId;
            Balance = 0;
        }

        public void Execute(UnitOfWork unitOfWork = null)
        {
            if (unitOfWork == null)
                throw new GfwTransactionInvalidException("功能事务作为原子操作是无效的。BargainRecordFacility");
            BargainAgencyRepository agencyRep = new BargainAgencyRepository();
            var agency = agencyRep.Get(_agencyId, unitOfWork);
            if (agency.AgencyCount - agency.TradeCount < _count)
                throw new GfwException("成交余额不足。");
            var date = DateTime.Now;
            agency.TradeDate = date;
            agency.TradeCount += _count;
            agency.TradePrice = _price;
            agency.TradeStatus = agency.AgencyCount ==agency.TradeCount ? (int)TradeStatusEnum.Done : (int)TradeStatusEnum.PartDone;
            agency.TradeTotal += _price * _count;

            StkBargainrecord record = new StkBargainrecord()
                                          {
                                              Id = Guid.NewGuid().ToString(),
                                              ActualCount = _count,
                                              ActualPrice = _price,
                                              AgencyCount = agency.AgencyCount,
                                              AgencyId = agency.Id,
                                              AgencyPrice = agency.AgencyPrice,
                                              AwardSerialNo =
                                                  agency.TradeType == (int)TradeTypeEnum.Sell
                                                      ? Guid.NewGuid().ToString()
                                                      : "",
                                              BargainDate = date,
                                              BargainType = agency.TradeType,
                                              TotalPrice = _price * _count,
                                              Userid = agency.Userid,
                                              Income = 0,
                                              Taxation = 0,
                                              AccountType = agency.AccountType
                                          };

            #region 更改用户帐户信息
            //如果是普通用户交易
            if (agency.AccountType == (int)AccountTypeEnum.User)
            {
                UserAccountRepository accountRep = new UserAccountRepository();
                var account = accountRep.Get(agency.Userid,unitOfWork);
                //如果是卖出股票，则需要计算综合税费和个人所得，并启用动态奖金分配
                if (record.BargainType == (int) TradeTypeEnum.Sell)
                {

                    StockAllot allot = new StockAllot(account, _price*_count);
                    allot.Execute(unitOfWork);

                    //调用动态奖金
                    record.Income = allot.Income();
                    record.Taxation = allot.AllTax();

                    

                    //股票销售收入，纳入动态奖金计算
                    //account.StockMoney += record.Income;
                }
                else if (record.BargainType == (int) TradeTypeEnum.Buy)
                {
                    //买入股票，需要更新用户的股票帐户信息
                    account.StockCount += _count;
                    if(account.FirstTimePrice == 0)
                    {
                        account.FirstTimePrice = _price;
                        account.NextAutoSellPrice = _price + EnforceSell;
                        account.LastAutoSellPrice = _price + EnforceSell;
                    }
                }
                accountRep.Update(account, unitOfWork);
                Balance = account.StockMoney;
            }
                //如果是公司帐户交易
            else if (agency.AccountType == (int)AccountTypeEnum.Admin)
            {
                AdminAccountRepository accountRep = new AdminAccountRepository();
                var account = accountRep.Unique(unitOfWork);
                if(record.BargainType == (int) TradeTypeEnum.Sell)
                {
                    account.StockMoney += _count*_price;
                }
                else if (record.BargainType == (int)TradeTypeEnum.Buy)
                {
                    account.StockCount += _count;
                }
                accountRep.Update(account, unitOfWork);
            }
            #endregion 更改用户帐户信息

            BargainRecordRepository recordRep = new BargainRecordRepository();
            recordRep.Save(record, unitOfWork);
            agencyRep.Update(agency, unitOfWork);

        }

        public decimal Balance
        {
            get;
            set;
        }
    }
}
